package com.pgeg.mixin.mana;

import com.pgeg.api.mana.IManaHandler;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.entity.data.DataTracker;
import net.minecraft.entity.data.TrackedData;
import net.minecraft.entity.data.TrackedDataHandlerRegistry;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import static com.pgeg.util.Reference.MODID;

@Mixin(PlayerEntity.class)
public abstract class ManaDataMixin extends LivingEntity implements IManaHandler {

    private static final TrackedData<Float> MANA;
    private static final TrackedData<Float> MAX_MANA;
    private static final int REGEN_SPEED = 20;
    private static final float REGEN_AMOUNT = 1.0f;

    static {
        MANA = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.FLOAT);
        MAX_MANA = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.FLOAT);
    }

    public ManaDataMixin(EntityType<? extends LivingEntity> entityType, World world) {
        super(entityType, world);
    }

    @Override
    public void setMana(float mana) {
        this.dataTracker.set(MANA, Math.min(getMaxMana(), mana));
    }

    @Override
    public void setMaxMana(float maxMana) {
        this.dataTracker.set(MANA, MathHelper.clamp(maxMana, 0.0F, this.getMaxMana()));
    }

    @Override
    public void regenMana(float mana) {
        this.setMana(this.getMana() + mana);
    }

    @Override
    public float getMana() {
        return this.dataTracker.get(MANA);
    }

    @Override
    public float getMaxMana() {
        return (float) this.getAttributeValue(EntityAttributes.GENERIC_MAX_HEALTH);
    }

    @Override
    public void reduceMana(float mana) {
        this.setMana(this.getMana() - mana);
    }

    @Inject(method = "tick", at = @At("RETURN"))
    private void onPlayerUpdate(CallbackInfo ci) {
        if (this.getMana() < this.getMaxMana() && this.age % REGEN_SPEED == 0) {
            regenMana(REGEN_AMOUNT);
        }
    }

    @Inject(method = "initDataTracker", at = @At("TAIL"))
    private void manaInit(CallbackInfo ci) {
        this.dataTracker.startTracking(MAX_MANA, 0.0F);
        this.dataTracker.startTracking(MANA, 0.0F);
    }

    @Inject(method = "writeCustomDataToNbt", at = @At("RETURN"))
    private void writeMana(NbtCompound compound, CallbackInfo ci) {
        compound.putFloat(MODID + ":MaxMana", this.getMaxMana());
        compound.putFloat(MODID + ":Mana", this.getMana());
    }

    @Inject(method = "readCustomDataFromNbt", at = @At("RETURN"))
    private void readMana(NbtCompound compound, CallbackInfo ci) {
        this.setMaxMana(compound.getFloat(MODID + ":MaxMana"));
        this.setMana(compound.getFloat(MODID + ":Mana"));
    }

}
